import { Router } from 'express';
import { body, param, query } from 'express-validator';
import multer from 'multer';
import path from 'path';
import fs from 'fs';
import { authenticateToken, authorizeRole } from '../middleware/auth';
import { validateRequest } from '../middleware/validation';
import { config } from '../config';
import { prisma } from '../lib/prisma';

const router = Router();

// 配置文件存储
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const uploadDir = path.join(process.cwd(), 'uploads');
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }
    cb(null, uploadDir);
  },
  filename: (req, file, cb) => {
    // 🔴 修复：保持原始文件名，只添加唯一后缀避免冲突
    console.log('Multer filename 配置 - 文件信息:');
    console.log('- originalname:', file.originalname);
    console.log('- fieldname:', file.fieldname);
    console.log('- mimetype:', file.mimetype);
    
    // 获取文件扩展名
    let ext = '';
    if (file.originalname && file.originalname.includes('.')) {
      ext = path.extname(file.originalname);
    } else if (file.mimetype) {
      // 如果 originalname 没有扩展名，根据 mimetype 推断
      const mimeToExt: { [key: string]: string } = {
        'image/jpeg': '.jpg',
        'image/png': '.png',
        'image/gif': '.gif',
        'image/webp': '.webp',
        'application/pdf': '.pdf',
        'application/msword': '.doc',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
        'text/plain': '.txt',
        'text/markdown': '.md',
        'application/json': '.json',
        'application/xml': '.xml'
      };
      ext = mimeToExt[file.mimetype] || '';
    }
    
    console.log('- 推断的扩展名:', ext);
    
    // 🔴 关键修复：在 Windows 系统上强制使用 UTF-8 编码处理中文文件名
    let finalFilename = file.originalname || `file-${Date.now()}${ext}`;
    
    // 检查是否包含中文字符
    if (/[\u4e00-\u9fa5]/.test(finalFilename)) {
      try {
        // 在 Windows 系统上，multer 可能会将中文文件名转换为系统编码
        // 我们需要确保文件名以 UTF-8 编码保存
        const buffer = Buffer.from(finalFilename, 'utf8');
        finalFilename = buffer.toString('utf8');
        console.log('✅ 中文文件名 UTF-8 编码处理:', finalFilename);
      } catch (error) {
        console.log('⚠️ 中文文件名编码处理失败，使用原始文件名');
        finalFilename = file.originalname || `file-${Date.now()}${ext}`;
      }
    }
    
    console.log('- 最终文件名:', finalFilename);
    console.log('- 使用原始文件名，无后缀');
    
    cb(null, finalFilename);
  }
});

// 文件过滤器
const fileFilter = (req: any, file: Express.Multer.File, cb: multer.FileFilterCallback) => {
  // 允许的文件类型
  const allowedMimeTypes = [
    'image/jpeg',
    'image/png',
    'image/gif',
    'image/webp',
    'application/pdf',
    'application/msword',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'text/plain',
    'text/markdown',
    'application/json',
    'application/xml'
  ];

  if (allowedMimeTypes.includes(file.mimetype)) {
    cb(null, true);
  } else {
    cb(new Error('不支持的文件类型'));
  }
};

// 配置multer
const upload = multer({
  storage,
  fileFilter,
  limits: {
    fileSize: 10 * 1024 * 1024, // 10MB
    files: 5 // 最多5个文件
  }
});

// 上传单个文件
router.post('/single',
  authenticateToken,
  upload.single('file'),
  async (req, res) => {
    try {
      if (!req.file) {
        return res.status(400).json({ success: false, error: '请选择要上传的文件' });
      }

      const { originalname, filename, mimetype, size, path: filePath } = req.file;
      
      // 🔴 关键：处理文件名编码问题
      let decodedOriginalName = originalname;
      console.log('🔍 接收到的文件名信息:');
      console.log('- originalname (原始):', originalname);
      console.log('- filename (生成):', filename);
      console.log('- mimetype:', mimetype);
      
      try {
        // 检查是否是URL编码
        if (originalname.includes('%')) {
          decodedOriginalName = decodeURIComponent(originalname);
          console.log('✅ URL解码成功:', originalname, '->', decodedOriginalName);
        }
        // 检查是否是UTF-8乱码（常见的中文字符乱码模式）
        else if (/[äåçèéêëìíîïðñòóôõöøùúûüýþÿ]/.test(originalname)) {
          // 尝试使用 Buffer 进行 UTF-8 解码
          try {
            const buffer = Buffer.from(originalname, 'latin1');
            decodedOriginalName = buffer.toString('utf8');
            console.log('✅ UTF-8解码成功:', originalname, '->', decodedOriginalName);
          } catch (bufferError) {
            console.log('❌ UTF-8解码失败:', bufferError.message);
            decodedOriginalName = originalname;
          }
        }
        // 检查是否包含中文字符但显示正常
        else if (/[\u4e00-\u9fa5]/.test(originalname)) {
          console.log('✅ 中文文件名正常:', originalname);
          decodedOriginalName = originalname;
        }
        else {
          console.log('ℹ️ 英文文件名:', originalname);
          decodedOriginalName = originalname;
        }
      } catch (error) {
        console.error('❌ 文件名解码失败:', error);
        decodedOriginalName = originalname; // 解码失败时使用原文件名
      }
      
      console.log('📝 最终使用的文件名:', decodedOriginalName);
      
      // 生成文件URL
      const fileUrl = `${config.BASE_URL}/uploads/${filename}`;

      // 🔴 关键修复：在 Windows 系统上，手动重命名文件为正确的中文名
      let finalFilePath = filePath;
      let finalFilename = filename;
      
      if (/[\u4e00-\u9fa5]/.test(decodedOriginalName)) {
        try {
          // 构建新的文件路径，使用正确的中文文件名
          const uploadDir = path.dirname(filePath);
          const newFilePath = path.join(uploadDir, decodedOriginalName);
          
          // 重命名文件
          if (fs.existsSync(filePath)) {
            fs.renameSync(filePath, newFilePath);
            finalFilePath = newFilePath;
            finalFilename = decodedOriginalName;
            console.log('✅ 文件重命名成功:', filePath, '->', newFilePath);
          }
        } catch (renameError) {
          console.error('❌ 文件重命名失败:', renameError);
          // 重命名失败时，保持原文件名
          finalFilePath = filePath;
          finalFilename = filename;
        }
      }
      
      // 重新生成文件URL
      const finalFileUrl = `${config.BASE_URL}/uploads/${finalFilename}`;
      
      // 保存文件信息到数据库
      const fileUpload = await prisma.fileUpload.create({
        data: {
          filename: finalFilename, // 使用重命名后的文件名
          originalName: decodedOriginalName, // 使用解码后的文件名
          mimeType: mimetype,
          size,
          url: finalFileUrl, // 使用新的URL
          path: finalFilePath, // 使用新的文件路径
          uploadedById: req.user.id
        },
        select: {
          id: true,
          filename: true,
          originalName: true,
          mimeType: true,
          size: true,
          url: true,
          path: true,
          createdAt: true
        }
      });

      res.status(201).json({ code: 200, data: fileUpload });
    } catch (error) {
      console.error('文件上传失败:', error);
      res.status(500).json({ success: false, error: '文件上传失败' });
    }
  }
);

// 上传多个文件
router.post('/multiple',
  authenticateToken,
  upload.array('files', 5),
  async (req, res) => {
    try {
      if (!req.files || req.files.length === 0) {
        return res.status(400).json({ success: false, error: '请选择要上传的文件' });
      }

      const files = req.files as Express.Multer.File[];
      const uploadedFiles = [];

      for (const file of files) {
        const { originalname, filename, mimetype, size, path: filePath } = file;
        
        // 🔴 关键：解码前端传来的编码文件名
        let decodedOriginalName = originalname;
        try {
          if (originalname.includes('%')) {
            decodedOriginalName = decodeURIComponent(originalname);
            console.log('文件名解码:', originalname, '->', decodedOriginalName);
          }
        } catch (error) {
          console.error('文件名解码失败:', error);
          decodedOriginalName = originalname; // 解码失败时使用原文件名
        }
        
        // 🔴 关键修复：在 Windows 系统上，手动重命名文件为正确的中文名
        let finalFilePath = filePath;
        let finalFilename = filename;
        
        if (/[\u4e00-\u9fa5]/.test(decodedOriginalName)) {
          try {
            // 构建新的文件路径，使用正确的中文文件名
            const uploadDir = path.dirname(filePath);
            const newFilePath = path.join(uploadDir, decodedOriginalName);
            
            // 重命名文件
            if (fs.existsSync(filePath)) {
              fs.renameSync(filePath, newFilePath);
              finalFilePath = newFilePath;
              finalFilename = decodedOriginalName;
              console.log('✅ 批量上传文件重命名成功:', filePath, '->', newFilePath);
            }
          } catch (renameError) {
            console.error('❌ 批量上传文件重命名失败:', renameError);
            // 重命名失败时，保持原文件名
            finalFilePath = filePath;
            finalFilename = filename;
          }
        }
        
        // 重新生成文件URL
        const finalFileUrl = `${config.BASE_URL}/uploads/${finalFilename}`;

        // 保存文件信息到数据库
        const fileUpload = await prisma.fileUpload.create({
          data: {
            filename: finalFilename, // 使用重命名后的文件名
            originalName: decodedOriginalName, // 使用解码后的文件名
            mimeType: mimetype,
            size,
            url: finalFileUrl, // 使用新的URL
            path: finalFilePath, // 使用新的文件路径
            uploadedById: req.user.id
          },
          select: {
            id: true,
            filename: true,
            originalName: true,
            mimeType: true,
            size: true,
            url: true,
            path: true,
            createdAt: true
          }
        });

        uploadedFiles.push(fileUpload);
      }

      res.status(201).json({ 
        code: 200, 
        data: {
          files: uploadedFiles,
          count: uploadedFiles.length
        }
      });
    } catch (error) {
      console.error('批量文件上传失败:', error);
      res.status(500).json({ success: false, error: '批量文件上传失败' });
    }
  }
);

// 获取文件列表
router.get('/',
  authenticateToken,
  [
    query('page').optional().isInt({ min: 1 }).withMessage('页码必须是正整数'),
    query('limit').optional().isInt({ min: 1, max: 100 }).withMessage('每页数量必须在1-100之间'),
    query('search').optional().isString().trim(),
    query('mimeType').optional().isString().trim(),
    query('uploadedBy').optional().isString()
  ],
  validateRequest,
  async (req, res) => {
    try {
      const { 
        page = 1, 
        limit = 20, 
        search, 
        mimeType, 
        uploadedBy 
      } = req.query;
      const skip = (Number(page) - 1) * Number(limit);

      // 构建查询条件
      const where: any = {};
      if (search) {
        where.OR = [
          { originalName: { contains: search as string, mode: 'insensitive' } },
          { filename: { contains: search as string, mode: 'insensitive' } }
        ];
      }
      if (mimeType) where.mimeType = mimeType;
      
      // 权限控制：如果不是管理员，只能查看自己上传的文件
      const userRole = req.user?.role;
      if (userRole !== 'ADMIN') {
        where.uploadedById = req.user?.id;
      } else if (uploadedBy) {
        // 管理员可以按用户ID过滤
        where.uploadedById = uploadedBy;
      }

      // 查询文件
      const [files, total] = await Promise.all([
                 prisma.fileUpload.findMany({
           where,
           select: {
             id: true,
             filename: true,
             originalName: true,
             mimeType: true,
             size: true,
             url: true,
             path: true,
             createdAt: true,
             uploadedBy: {
               select: {
                 id: true,
                 username: true,
                 avatar: true
               }
             }
           },
           skip,
           take: Number(limit),
           orderBy: { createdAt: 'desc' }
         }),
        prisma.fileUpload.count({ where })
      ]);

      res.json({
        code: 200,
        message: '操作成功',
        data: {
          files,
          pagination: {
            page: Number(page),
            limit: Number(limit),
            total,
            pages: Math.ceil(total / Number(limit))
          }
        }
      });
    } catch (error) {
      console.error('获取文件列表失败:', error);
      res.status(500).json({ success: false, error: '获取文件列表失败' });
    }
  }
);

// 获取单个文件信息
router.get('/:id',
  authenticateToken,
  [
    param('id').isString().notEmpty().withMessage('文件ID不能为空')
  ],
  validateRequest,
  async (req, res) => {
    try {
      const { id } = req.params;
      const file = await prisma.fileUpload.findUnique({
        where: { id },
        select: {
          id: true,
          filename: true,
          originalName: true,
          mimeType: true,
          size: true,
          url: true,
          path: true,
          createdAt: true,
          uploadedBy: {
            select: {
              id: true,
              username: true,
              avatar: true
            }
          }
        }
      });

      if (!file) {
        return res.status(404).json({ success: false, error: '文件不存在' });
      }

      res.json({
        code: 200,
        message: '操作成功',
        data: file });
    } catch (error) {
      console.error('获取文件信息失败:', error);
      res.status(500).json({ success: false, error: '获取文件信息失败' });
    }
  }
);

// 下载文件
router.get('/:id/download',
  authenticateToken,
  [
    param('id').isString().notEmpty().withMessage('文件ID不能为空')
  ],
  validateRequest,
  async (req, res) => {
    try {
      const { id } = req.params;
      const file = await prisma.fileUpload.findUnique({
        where: { id },
        select: {
          filename: true,
          originalName: true,
          mimeType: true,
          path: true
        }
      });

      if (!file) {
        return res.status(404).json({ success: false, error: '文件不存在' });
      }

      // 检查文件是否存在
      if (!fs.existsSync(file.path)) {
        return res.status(404).json({ success: false, error: '文件不存在于服务器' });
      }

      // 设置响应头
      res.setHeader('Content-Type', file.mimeType);
      res.setHeader('Content-Disposition', `attachment; filename="${encodeURIComponent(file.originalName)}"`);

      // 发送文件
      res.sendFile(file.path);
    } catch (error) {
      console.error('文件下载失败:', error);
      res.status(500).json({ success: false, error: '文件下载失败' });
    }
  }
);

// 删除文件
router.delete('/:id',
  authenticateToken,
  [
    param('id').isString().notEmpty().withMessage('文件ID不能为空')
  ],
  validateRequest,
  async (req, res) => {
    try {
      const { id } = req.params;

      // 检查文件是否存在
      const file = await prisma.fileUpload.findUnique({
        where: { id },
        select: {
          path: true,
          uploadedById: true
        }
      });

      if (!file) {
        return res.status(404).json({ success: false, error: '文件不存在' });
      }

      // 检查权限（只能删除自己的文件，管理员可以删除所有）
      if (req.user.role !== 'ADMIN' && file.uploadedById !== req.user.id) {
        return res.status(403).json({ success: false, error: '没有权限删除此文件' });
      }

      // 删除物理文件
      if (fs.existsSync(file.path)) {
        fs.unlinkSync(file.path);
      }

      // 删除数据库记录
      await prisma.fileUpload.delete({ where: { id } });

      res.json({ code: 200, message: '文件删除成功' });
    } catch (error) {
      console.error('删除文件失败:', error);
      res.status(500).json({ success: false, error: '删除文件失败' });
    }
  }
);

// 批量删除文件
router.delete('/batch',
  authenticateToken,
  authorizeRole(['ADMIN']),
  [
    body('fileIds').isArray({ min: 1 }).withMessage('文件ID数组不能为空'),
    body('fileIds.*').isString().notEmpty().withMessage('文件ID不能为空')
  ],
  validateRequest,
  async (req, res) => {
    try {
      const { fileIds } = req.body;
      const deletedFiles = [];
      const errors = [];

      for (const fileId of fileIds) {
        try {
          // 检查文件是否存在
          const file = await prisma.fileUpload.findUnique({
            where: { id: fileId },
            select: {
              id: true,
              originalName: true,
              path: true
            }
          });

          if (!file) {
            errors.push({ id: fileId, error: '文件不存在' });
            continue;
          }

          // 删除物理文件
          if (fs.existsSync(file.path)) {
            fs.unlinkSync(file.path);
          }

          // 删除数据库记录
          await prisma.fileUpload.delete({ where: { id: fileId } });
          deletedFiles.push({ id: fileId, name: file.originalName });
        } catch (error) {
          errors.push({ id: fileId, error: '删除失败' });
        }
      }

      res.json({
        code: 200,
        message: '操作成功',
        data: {
          deletedFiles,
          errors,
          summary: {
            total: fileIds.length,
            success: deletedFiles.length,
            failed: errors.length
          }
        }
      });
    } catch (error) {
      console.error('批量删除文件失败:', error);
      res.status(500).json({ success: false, error: '批量删除文件失败' });
    }
  }
);

// 获取文件统计信息
router.get('/stats/overview',
  authenticateToken,
  async (req, res) => {
    try {
      const userId = req.user?.id;
      const userRole = req.user?.role;
      
      if (!userId) {
        return res.status(401).json({ 
          code: 401, 
          message: '用户未认证' 
        });
      }

      let whereClause = {};
      
      // 如果不是管理员，只能查看自己上传的文件统计
      if (userRole !== 'ADMIN') {
        whereClause = { uploadedById: userId };
      }

      const [
        totalFiles,
        totalSize,
        filesByType,
        recentFiles,
        filesByMonth
      ] = await Promise.all([
        prisma.fileUpload.count({ where: whereClause }),
        prisma.fileUpload.aggregate({
          where: whereClause,
          _sum: { size: true }
        }),
        prisma.fileUpload.groupBy({
          by: ['mimeType'],
          where: whereClause,
          _count: { mimeType: true },
          _sum: { size: true },
          orderBy: {
            _count: {
              mimeType: 'desc'
            }
          },
          take: 10
        }),
        prisma.fileUpload.findMany({
          where: whereClause,
          select: {
            id: true,
            originalName: true,
            mimeType: true,
            size: true,
            createdAt: true
          },
          orderBy: { createdAt: 'desc' },
          take: 10
        }),
        prisma.fileUpload.groupBy({
          by: ['createdAt'],
          where: whereClause,
          _count: { createdAt: true },
          _sum: { size: true },
          orderBy: { createdAt: 'desc' },
          take: 12
        })
      ]);

      res.json({
        code: 200,
        message: '获取文件统计成功',
        data: {
          totalFiles,
          totalSize: totalSize._sum.size || 0,
          filesByType,
          recentFiles,
          filesByMonth,
          scope: userRole === 'ADMIN' ? 'all' : 'user'
        }
      });
    } catch (error) {
      console.error('获取文件统计失败:', error);
      res.status(500).json({ 
        code: 500, 
        message: '获取文件统计失败',
        error: error instanceof Error ? error.message : '未知错误'
      });
    }
  }
);

export { router as uploadRoutes };
